import numpy as np
import sqlite3
import math
from dataStruct import *


def generate_matU():
    # Initialize basic User-Item Matrix matU
    matU = np.zeros([100, 450], float)

    # Fetch data from database
    conn = sqlite3.connect('./data/videoset.db')
    cur = conn.cursor()
    cur.execute("SELECT * FROM UserFeedback")
    tmplst = cur.fetchall()
    cur.close()
    conn.close()

    # Fill data into matU
    for row in tmplst:
        pred = sum(row[3:])
        rvalue = 1 + math.log(1 + (math.exp(4)-1) / 8 * pred)
        matU[row[1]][row[2]] = rvalue

    return matU


def similarityMatrix():
    # Initialize similarity matrix matS
    matS = np.zeros([450, 450], float)

    # fetch video data from database
    conn = sqlite3.connect('./data/videoset.db')
    cur = conn.cursor()
    cur.execute("SELECT * FROM Video")
    tmplst = cur.fetchall()
    cur.close()
    conn.close()

    # process video data using self-defined class Video
    res = []
    for row in tmplst:
        maintype = row[10]
        tag = eval(row[11])
        video = Video(row[0], maintype, tag)
        res.append(video)

    # calculate similarity and update matS
    for i in range(450):
        for j in range(i+1, 450):
            tmp = [t for t in res[i].tag if t in res[j].tag]
            matS[i][j] = len(tmp) / (len(res[i].tag) * len(res[j].tag))
    matS = matS.T + matS

    return matS


def derive_matR(matU, matS, k):
    users = []
    for uid in range(100):
        firstexp = [j for j in range(450) if matU[uid][j]]
        user = User(uid, firstexp)
        users.append(user)
    matR = np.array(matU, copy=True)   # 矩阵深拷贝

    # 通过协同过滤算法计算用户对未被推送视频的偏好
    for uid in range(100):
        for vid in range(450):
            if not matR[uid][vid]:
                ratedsim = {}
                for j in users[uid].videomarked:
                    ratedsim[j] = matS[vid][j]
                tmp_ratedsim = list(ratedsim.items())
                tmp_ratedsim.sort(key=lambda x:x[1], reverse=True)
                totalsum, simsum = 0, 0
                for j in range(k):
                    totalsum += tmp_ratedsim[j][1] * matU[uid][tmp_ratedsim[j][0]]
                    simsum += tmp_ratedsim[j][1]
                matR[uid][vid] = totalsum / simsum
    return matR

if __name__ == '__main__':
    matU = generate_matU()
    matS = similarityMatrix()
    matR = derive_matR(matU, matS, 10)
    print(matR)
